package dao

import (
	"context"
	"mini-app/internal/dal"
	"mini-app/internal/models"
	"strconv"
	"time"
)

type AdRefundDao struct{}

// Create creates a new refund record
func (AdRefundDao) Create(ctx context.Context, query *dal.Query, orderID string, amount int64, remark string, paidID string, userID, userName string) (err error) {
	o := query.AdRefund
	id := strconv.FormatInt(time.Now().UnixNano(), 10)

	// Get advertisement info to get openID
	ad, err := Advertisement{}.Detail(ctx, query, orderID)
	if err != nil {
		return err
	}

	refund := &models.AdRefund{
		ID:        id,
		OrderID:   orderID,
		Amount:    amount,
		Remark:    remark,
		CreatedAt: time.Now().Unix(),
		PaidID:    paidID,
		OpenID:    ad.OpenID,
		UserID:    userID,
		UserName:  userName,
	}

	err = o.WithContext(ctx).Create(refund)
	return
}

// GetByOrderID retrieves a refund record by order ID
func (AdRefundDao) GetByOrderID(ctx context.Context, query *dal.Query, orderID string) (res *models.AdRefund, err error) {
	o := query.AdRefund
	tx := o.WithContext(ctx).Where(o.OrderID.Eq(orderID))
	res, err = tx.First()
	return
}

// GetByPaidID retrieves a refund record by paid ID
func (AdRefundDao) GetByPaidID(ctx context.Context, query *dal.Query, paidID string) (res *models.AdRefund, err error) {
	o := query.AdRefund
	tx := o.WithContext(ctx).Where(o.PaidID.Eq(paidID))
	res, err = tx.First()
	return
}

// List retrieves refund records with pagination
func (AdRefundDao) List(ctx context.Context, query *dal.Query, order_id string, start_time, end_time int64, openid string, user_id, user_name string, page, limit int) (res []*models.AdRefund, total int64, err error) {
	o := query.AdRefund
	tx := o.WithContext(ctx)

	if order_id != "" {
		tx = tx.Where(o.OrderID.Eq(order_id))
	}

	if start_time > 0 && end_time > 0 {
		tx = tx.Where(o.CreatedAt.Between(start_time, end_time))
	}

	if openid != "" {
		tx = tx.Where(o.OpenID.Eq(openid))
	}

	if page > 0 && limit > 0 {
		offset := (page - 1) * limit
		tx = tx.Offset(offset).Limit(limit)
	}
	if user_id != "" {
		tx = tx.Where(o.UserID.Eq(user_id))
	}
	if user_name != "" {
		tx = tx.Where(o.UserName.Eq(user_name))
	}
	total, err = tx.Count()
	if err != nil {
		return
	}

	res, err = tx.Find()
	return
}

// UpdateRemark updates the remark of a refund record
func (AdRefundDao) UpdateRemark(ctx context.Context, query *dal.Query, orderID string, remark string) (err error) {
	o := query.AdRefund
	tx := o.WithContext(ctx).Where(o.OrderID.Eq(orderID))
	tx.UpdateColumn(o.Remark, remark)
	return
}

// UpdateAmount updates the amount of a refund record
func (AdRefundDao) UpdateAmount(ctx context.Context, query *dal.Query, orderID string, amount int64) (err error) {
	o := query.AdRefund
	tx := o.WithContext(ctx).Where(o.OrderID.Eq(orderID))
	tx.UpdateColumn(o.Amount, amount)
	return
}

// Delete deletes a refund record
func (AdRefundDao) Delete(ctx context.Context, query *dal.Query, orderID string) (err error) {
	o := query.AdRefund
	o.WithContext(ctx).Where(o.OrderID.Eq(orderID)).Delete()
	return
}

// GetByTimeRange retrieves refund records within a time range
func (AdRefundDao) GetByTimeRange(ctx context.Context, query *dal.Query, startTime, endTime int64) (res []*models.AdRefund, err error) {
	o := query.AdRefund
	tx := o.WithContext(ctx).Where(o.CreatedAt.Between(startTime, endTime))
	res, err = tx.Find()
	return
}

// GetByOpenID retrieves refund records by openid
func (AdRefundDao) GetByOpenID(ctx context.Context, query *dal.Query, openID string) (res []*models.AdRefund, err error) {
	o := query.AdRefund
	tx := o.WithContext(ctx).Where(o.OpenID.Eq(openID))
	res, err = tx.Find()
	return
}
